/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import 'dart:ui';

import 'package:hadss_adaptive_video/immersion/adaptive_immersion.dart';

const double _windowAspectRatio_9_20 = 9 / 20;
const double _windowAspectRatio_9_18 = 9 / 18;
const double _windowAspectRatio_9_17o8 = 9 / 17.8;
const double _windowAspectRatio_9_14o4 = 9 / 14.4;
const double _windowAspectRatio_9_10o8 = 9 / 10.8;
const double _windowAspectRatio_9_7o2 = 9 / 7.2;

const MathRange _windowWidthRange = MathRange(min: 0);

/// 返回沉浸信息
typedef ImmersionInfoCallback = ImmersionInfo Function(
  double videoAspectRatio,
  Size windowSize,
  double bottomTabHeight,
  double topStatusBarHeight,
);

double safeDivide(double numerator, double denominator) {
  if (denominator == 0) {
    return 0; // 或其他默认值/处理逻辑
  }
  return numerator / denominator;
}

/// 沉浸规则
class ImmersionRule {
  final MathRange windowWidthRange;
  final MathRange windowRatioRange;
  final ImmersionInfoCallback getImmersionInfo;

  ImmersionRule(
      {required this.windowWidthRange,
      required this.windowRatioRange,
      required this.getImmersionInfo});
}

/// 区间 [min, max)
class MathRange {
  final double min;
  final double? max; // null表示无穷大

  const MathRange({required this.min, this.max});

  bool contains(double value) {
    return value >= min && (max == null || value < max!);
  }

  @override
  String toString() {
    return max == null ? '[$min, +∞)' : '[$min, $max)';
  }
}

/// 默认沉浸规则：
/// 视频显示区域：高度减去状态栏和顶部tab后居中
/// 自适应规则： 可视区域比例>=视频比例时，高度撑满，宽度自适应；反之宽度撑满
ImmersionRule defaultImmersionRule = ImmersionRule(
    windowWidthRange: _windowWidthRange,
    windowRatioRange: const MathRange(min: 0),
    getImmersionInfo: (double videoAspectRatio, Size windowSize,
        double bottomTabHeight, double topStatusBarHeight) {
      double videoWidth;
      double videoHeight;
      Offset position;
      double displayHeight =
          windowSize.height - bottomTabHeight - topStatusBarHeight;
      double displayAspectRatio = safeDivide(windowSize.width, displayHeight);
      if (displayAspectRatio >= videoAspectRatio) {
        videoHeight = displayHeight;
        videoWidth = videoHeight * videoAspectRatio;
        position =
            Offset((windowSize.width - videoWidth) / 2, topStatusBarHeight);
      } else {
        videoWidth = windowSize.width;
        videoHeight = videoWidth / videoAspectRatio;
        position = Offset(
            0,
            topStatusBarHeight +
                (windowSize.height -
                        videoHeight -
                        bottomTabHeight -
                        topStatusBarHeight) /
                    2);
      }
      return ImmersionInfo(
          videoSize: Size(videoWidth, videoHeight),
          videoPosition: position,
          immersionSetting: ImmersionSetting(
              isBottomTabImmersive: false, isStatusBarImmersive: false));
    });

/// 该规则目前仅使用与9/16的视频比例
final List<ImmersionRule> immersionRules = [
  /// 沉浸规则：窗口[0,+∞)，比例 [0, 9/20)
  /// 视频显示区域：高度减去状态栏和底部tab后居中
  /// 自适应规则：宽度自适应裁剪到 9 / 17.8，高度根据视频比例拉伸
  ImmersionRule(
      windowWidthRange: _windowWidthRange,
      windowRatioRange: const MathRange(min: 0, max: _windowAspectRatio_9_20),
      getImmersionInfo: (double videoAspectRatio, Size windowSize,
          double bottomTabHeight, double topStatusBarHeight) {
        double displayHeight =
            windowSize.height - bottomTabHeight - topStatusBarHeight;
        double videoWidth =
            windowSize.width / _windowAspectRatio_9_17o8 * videoAspectRatio;
        double videoHeight = videoWidth / videoAspectRatio;
        return ImmersionInfo(
            videoSize: Size(videoWidth, videoHeight),
            videoPosition: Offset((windowSize.width - videoWidth) / 2,
                topStatusBarHeight + (displayHeight - videoHeight) / 2),
            immersionSetting: ImmersionSetting(
                isStatusBarImmersive: false, isBottomTabImmersive: false));
      }),

  /// 沉浸规则：窗口[0,+∞)，比例 [9/20, 9/18)
  /// 视频显示区域：高度减去底部tab
  /// 自适应规则：1、剩余区域 >= 9:16，宽撑满，上下自适应裁剪；
  /// 2、剩余区域 <9:16 && >= 9:17.8，高度撑满，但是需限制在最大9:17.8的范围内，若还有剩余高度，不做处理，左右自适应裁剪；
  ImmersionRule(
      windowWidthRange: _windowWidthRange,
      windowRatioRange: const MathRange(
          min: _windowAspectRatio_9_20, max: _windowAspectRatio_9_18),
      getImmersionInfo: (double videoAspectRatio, Size windowSize,
          double bottomTabHeight, double topStatusBarHeight) {
        double displayHeight = windowSize.height - bottomTabHeight;
        double displayRatio = windowSize.width / displayHeight;
        double videoWidth;
        double videoHeight;
        Offset position;
        // 剩余可视区域>=9:16，宽撑满，高裁剪
        if (displayRatio >= videoAspectRatio) {
          videoWidth = windowSize.width;
          videoHeight = videoWidth / videoAspectRatio;
          position = Offset(0, (displayHeight - videoHeight) / 2);
        } else if (displayRatio >= _windowAspectRatio_9_17o8) {
          videoHeight = displayHeight;
          videoWidth = videoHeight * videoAspectRatio;
          position = Offset((windowSize.width - videoWidth) / 2, 0);
        } else {
          videoWidth =
              windowSize.width / _windowAspectRatio_9_17o8 * videoAspectRatio;
          videoHeight = videoWidth / videoAspectRatio;
          position = Offset((windowSize.width - videoWidth) / 2, 0);
        }
        return ImmersionInfo(
            videoSize: Size(videoWidth, videoHeight),
            videoPosition: position,
            immersionSetting: ImmersionSetting(
                isStatusBarImmersive: true, isBottomTabImmersive: false));
      }),

  /// 沉浸规则：窗口[0,+∞)，比例 [9/18, 9/14.4)
  /// 视频显示区域：全屏显示
  /// 自适应规则：1、<=9/16 宽撑满；2、高撑满
  ImmersionRule(
      windowWidthRange: _windowWidthRange,
      windowRatioRange: const MathRange(
          min: _windowAspectRatio_9_18, max: _windowAspectRatio_9_14o4),
      getImmersionInfo: (double videoAspectRatio, Size windowSize,
          double bottomTabHeight, double topStatusBarHeight) {
        double displayRatio = windowSize.width / windowSize.height;
        double videoWidth;
        double videoHeight;
        Offset position;
        // 剩余可视区域小于等于9:16，宽撑满，高裁剪
        if (videoAspectRatio <= displayRatio) {
          videoWidth = windowSize.width;
          videoHeight = videoWidth / videoAspectRatio;
          position = Offset(0, (windowSize.height - videoHeight) / 2);
        } else {
          videoHeight = windowSize.height;
          videoWidth = videoHeight * videoAspectRatio;
          position = Offset((windowSize.width - videoWidth) / 2, 0);
        }
        return ImmersionInfo(
            videoSize: Size(videoWidth, videoHeight),
            videoPosition: position,
            immersionSetting: ImmersionSetting(
                isStatusBarImmersive: true, isBottomTabImmersive: true));
      }),

  /// 沉浸规则：窗口[0,+∞)，比例 [9/14.4, 9/10.8)
  /// 视频显示区域：全屏显示
  /// 自适应规则：高撑满
  ImmersionRule(
      windowWidthRange: _windowWidthRange,
      windowRatioRange: const MathRange(
          min: _windowAspectRatio_9_14o4, max: _windowAspectRatio_9_10o8),
      getImmersionInfo: (double videoAspectRatio, Size windowSize,
          double bottomTabHeight, double topStatusBarHeight) {
        double videoHeight = windowSize.height;
        double videoWidth = videoHeight * videoAspectRatio;
        return ImmersionInfo(
            videoSize: Size(videoWidth, videoHeight),
            videoPosition: Offset((videoWidth - windowSize.width) / 2, 0),
            immersionSetting: ImmersionSetting(
                isStatusBarImmersive: true, isBottomTabImmersive: true));
      }),

  /// 沉浸规则：窗口[0,+∞)，比例 [9/10.8, 9/7.2)
  /// 视频显示区域：全屏显示
  /// 自适应规则：高撑满
  ImmersionRule(
      windowWidthRange: _windowWidthRange,
      windowRatioRange: const MathRange(
          min: _windowAspectRatio_9_10o8, max: _windowAspectRatio_9_7o2),
      getImmersionInfo: (double videoAspectRatio, Size windowSize,
          double bottomTabHeight, double topStatusBarHeight) {
        double videoHeight = windowSize.height;
        double videoWidth = videoHeight * videoAspectRatio;
        return ImmersionInfo(
            videoSize: Size(videoWidth, videoHeight),
            videoPosition: Offset((videoWidth - windowSize.width) / 2, 0),
            immersionSetting: ImmersionSetting(
                isStatusBarImmersive: true, isBottomTabImmersive: true));
      }),

  /// 沉浸规则：窗口[0,+∞)，比例 [9/7.2, +∞)
  /// 视频显示区域：全屏显示
  /// 自适应规则：高撑满
  ImmersionRule(
      windowWidthRange: _windowWidthRange,
      windowRatioRange: const MathRange(min: _windowAspectRatio_9_7o2),
      getImmersionInfo: (double videoAspectRatio, Size windowSize,
          double bottomTabHeight, double topStatusBarHeight) {
        double videoHeight = windowSize.height;
        double videoWidth = videoHeight * videoAspectRatio;
        return ImmersionInfo(
            videoSize: Size(videoWidth, videoHeight),
            videoPosition: Offset((videoWidth - windowSize.width) / 2, 0),
            immersionSetting: ImmersionSetting(
                isStatusBarImmersive: true, isBottomTabImmersive: true));
      }),
];
